package sdkapi

import (
	"fabrictask/utils"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strconv"

	"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
	"github.com/hyperledger/fabric-sdk-go/pkg/gateway"
)

// var apiwallet *gateway.Wallet
// var gw *gateway.Gateway
var userContract *gateway.Contract
var taskContract *gateway.Contract
var tokenContract *gateway.Contract

//{"id":"2021October220000","name":"count(1+2+3)","issuer":"yekai","holder":"","status":0,"bonus":500,"task_time":0,"comment":""}
type FabTask struct {
	ID       int64  `json:"task_id"`
	Name     string `json:"name"`
	Issuer   string `json:"issuer"`
	Holder   string `json:"holder"`
	Status   int8   `json:"status"`
	Bonus    int    `json:"bonus"`
	TaskTime int64  `json:"task_time"`
	Comment  string `json:"comment"`
}

func init() {
	err := os.Setenv("DISCOVERY_AS_LOCALHOST", "false")
	if err != nil {
		log.Fatalf("Error setting DISCOVERY_AS_LOCALHOST environemnt variable: %v", err)
	}

	wallet, err := gateway.NewFileSystemWallet("config/wallet")
	if err != nil {
		log.Fatalf("Failed to create wallet: %v", err)
	}

	if !wallet.Exists("appUser") {
		log.Fatalf("wallet does not exists")
	}

	ccpPath := filepath.Join(
		"config",
		"connection-org1.yaml",
	)

	gw, err := gateway.Connect(
		gateway.WithConfig(config.FromFile(filepath.Clean(ccpPath))),
		gateway.WithIdentity(wallet, "appUser"),
	)
	if err != nil {
		log.Fatalf("Failed to connect to gateway: %v", err)
	}

	network, err := gw.GetNetwork("ykchannel")
	if err != nil {
		log.Fatalf("Failed to get network: %v", err)
	}

	contract := network.GetContract("users")

	if contract == nil {
		log.Fatalf("Failed to get users' contract")
	}

	userContract = contract

	// 任务合约
	contract = network.GetContract("tasks")

	if contract == nil {
		log.Fatalf("Failed to get tasks' contract")
	}

	taskContract = contract

	// 积分合约
	contract = network.GetContract("tokens")

	if contract == nil {
		log.Fatalf("Failed to get tokens' contract")
	}

	tokenContract = contract
}

func Register(id, name, pass string) ([]byte, error) {

	log.Println("--> Submit Transaction: Register, function Register to client")
	return userContract.SubmitTransaction("Register", id, pass, name)
}

func Login(name, pass string) ([]byte, error) {

	return userContract.EvaluateTransaction("Login", name, pass)
}

func Mint(toname string, amount int) ([]byte, error) {

	str_amount := fmt.Sprintf("%d", amount)
	log.Printf("--> Submit Transaction: Mint, function Mint to client(%s->%d)\n", toname, amount)
	return tokenContract.SubmitTransaction("Mint", toname, str_amount)
}

func IssueTask(taskname, issuer string, bonus int) ([]byte, error) {
	log.Printf("--> Submit Transaction: NewTask, function NewTask to client(%s,%s,%d)\n", taskname, issuer, bonus)

	return taskContract.SubmitTransaction("NewTask", issuer, taskname, strconv.Itoa(bonus))
}

func ChangeTask(taskid, operator, comment string, status int8) ([]byte, error) {

	if status == utils.STATUS_TAKE {
		log.Printf("--> Submit Transaction: TakeTask, function TakeTask to client(%s,%s,%d)\n", taskid, operator, status)

		return taskContract.SubmitTransaction("TakeTask", taskid, operator)

	} else if status == utils.STATUS_COMMIT {
		log.Printf("--> Submit Transaction: CommitTask, function CommitTask to client(%s,%s,%d)\n", taskid, operator, status)

		return taskContract.SubmitTransaction("CommitTask", taskid, operator)

	} else {
		log.Printf("--> Submit Transaction: ConfirmTask, function ConfirmTask to client(%s,%s,%d)\n", taskid, operator, status)
		if status != utils.STATUS_CONFRIM {
			status = utils.STATUS_TAKE
		}
		return taskContract.SubmitTransaction("ConfirmTask", taskid, operator, comment, fmt.Sprintf("%d", status))

	}

}

func BalanceOf(name string) ([]byte, error) {

	return tokenContract.EvaluateTransaction("BalanceOf", name)
}

func AllTasks(page string) ([]byte, error) {

	return taskContract.EvaluateTransaction("GetAllTask", page)

}
